package development.bussiness;

import java.util.Vector;

import state.AlertListener;
import state.GameAlert;
import state.GameControl;
import state.GameForm;
import state.GameGlobal;
import state.Transformer;
import state.socket.DataPackage;
import state.util.GameStringUtils;
import state.util.Hashtable;
import state.util.array.StringArray;
import development.Constants;
import development.FrmAcceptInviteGame;
import development.FrmAutoInviteGame;
import development.FrmChooseGame;
import development.FrmDownloadResource;
import development.FrmListFreeUser;
import development.FrmListRoom;
import development.FrmListTable;
import development.FrmLogin;
import development.FrmTable;
import development.Global;
import development.bean.Game;
import development.bean.Room;
import development.bean.Table;
import development.bean.User;
import development.bean.UserBean;
import development.game.FrmAilaTrieuPhuOff;
import development.game.FrmDaoVangOffline;
import development.group.FrmGroupListTableFreeUserChat;
import development.group.FrmGroupMenu;
import development.group.FrmGroupNapXuAndExchangeGold;
import development.group.FrmGroupTableFreeUserFriend;
import development.listener.DownloadResourceListener;
import development.socket.GameActionHandle;
import development.socket.ProtocolConstants;
import development.socket.SocketClientUtil;

public class GameBussiness implements AlertListener {
  public String invitedTableId;
  
  private String invitedGameId;
  
  private Hashtable roomMap = new Hashtable();
  private Hashtable tableMap = new Hashtable();

  public void alertEventPerform(int alertType, int eventType, int alertId) {
    // Auto invite game
    if (alertId == 100) {
      if (eventType == GameAlert.YES_BUTTON) {
        SocketClientUtil.notifyUserWaitingRoomState();
        GameGlobal.nextState(FrmAutoInviteGame.instance(), null);
      }
    }
    // Nếu đăng nhập vào GameService thất bại thì cho out ra màn hình đăng nhập để đăng nhập lại
    if (alertId == 99) {
      GameGlobal.nextState(FrmLogin.instance(), null);
    }

    // Khi user không đủ tiền so với đặt cược mới, thì thông báo và thoát ra danh sách bàn
    else if (alertId == 98) {
      GameGlobal.nextState(FrmGroupListTableFreeUserChat.instance(), null);
    }

    // Khi người điểm cược thay đổi và người chơi đủ tiền, hỏi người chơi là có muốn chơi tiếp không
    else if (alertId == 97 && eventType == GameAlert.NO_BUTTON) {
      SocketClientUtil.leaveTableRequest();
      GameGlobal.nextState(FrmGroupListTableFreeUserChat.instance(), null);
    }
    // Khi người chơi được mời tham gia vào 1 bàn có muốn tham gia
    else if (alertId == 96) {
      if (eventType == GameAlert.YES_BUTTON && invitedTableId != null) {
        if (Global.resourceConfig.get(invitedGameId) != null) {
          DownloadResourceListener downloadResourceListener = new DownloadResourceListener(invitedGameId);
          downloadResourceListener.nextForm = FrmAcceptInviteGame.instance();
          Global.authenticateHandle.addListener(downloadResourceListener);
          GameGlobal.nextState(FrmDownloadResource.instance(), null);
        } else {
          SocketClientUtil.acceptInviteUserToTable(invitedTableId);
        }
      }
    }

    // Khi người chơi không đủ tiền để chơi tiếp, hỏi xem người chơi có muốn nạp tiền hay không
    else if (alertId == 93) {
      if (eventType == GameAlert.YES_BUTTON) {
        FrmGroupNapXuAndExchangeGold.backForm = FrmGroupMenu.instance();
        Global.nextState(FrmGroupNapXuAndExchangeGold.instance(), null);
      } else {
        Global.nextState(FrmGroupListTableFreeUserChat.instance(), null);
      }
    }
    
    // Chấp nhận mời chơi vào bàn thất bại
    else if (alertId == 92) {
      if (Global.currentRoom != null) {
        if (!(Global.systemCanvas.frmCurrent instanceof FrmGroupListTableFreeUserChat)) {
          Global.nextState(FrmGroupListTableFreeUserChat.instance(), null);
        }
      } else {
        Global.nextState(FrmGroupMenu.instance(), null);
      }
    }
    
    // Nếu người chơi không đủ tiền để chơi game off
    else if (alertId == 90) {
      if (eventType == 0) {
        FrmGroupNapXuAndExchangeGold.backForm = FrmGroupMenu.instance();
        Global.nextState(FrmGroupNapXuAndExchangeGold.instance(), null);
        FrmGroupNapXuAndExchangeGold.setTab(1);
      } else if (eventType == 1) {
        FrmGroupNapXuAndExchangeGold.backForm = FrmGroupMenu.instance();
        Global.nextState(FrmGroupNapXuAndExchangeGold.instance(), null);
      } else if (eventType == 2) {
        FrmGroupMenu.tabIndex = 1;
        Global.nextState(FrmGroupMenu.instance(), null);
      }
    }
    
    // Khi vào phòng thất bại thì quay trở lại danh sách phòng
    else if (alertId == 89) {
      Global.nextState(FrmListRoom.instance(), null);
    }
  }

  public void onAuthenticateSuccess(DataPackage dataPackage) {
    GameActionHandle.isLoginSuccess = true;
    
    // Send the device solusion of client to server
    DataPackage deveiceSolusionPackage = DataPackage.createDataPackage1(ProtocolConstants.RequestHeader.CLIENT_DEVICE_NOTIFY_REQUEST);
    deveiceSolusionPackage.putInt(Constants.SCREEN_WIDTH);
    deveiceSolusionPackage.putInt(Constants.SCREEN_HEIGHT);
    Global.gameActionClient.write(deveiceSolusionPackage);

    // Go to next form
    if (!Constants.GAME_VERSION_INFO.equals("all")) {
      Global.currentGame = (Game) Global.gameMap.get(Constants.GAME_VERSION_INFO);
      SocketClientUtil.joinGameRequest(Constants.GAME_VERSION_INFO);
      if (Global.resourceConfig.get(Constants.GAME_VERSION_INFO) != null) {
        DownloadResourceListener downloadResourceListener = new DownloadResourceListener(Constants.GAME_VERSION_INFO);
        downloadResourceListener.nextForm = null;
        Global.authenticateHandle.addListener(downloadResourceListener);
      }
    }
  }

  public void onAuthenticateFail(DataPackage dataPackage) {
    GameGlobal.alert.showAlert1(this, GameAlert.OK_TYPE, StringArray.create1( "Đăng nhập vào server game thất bại", "Hãy thử đăng nhập lại" ), 99);
  }

  public void onNotEnoughMoneyToContinuePlayGame(DataPackage dataPackage) {
    Global.alert.showAlert1(this, GameAlert.YES_NO_TYPE, StringArray.create1( "Bạn không đủ tiền để chơi tiếp", "Bạn có muốn nạp thêm tiền" ), 93);
  }

  public void onListUsersWantToPlay(DataPackage dataPackage) {
    FrmListFreeUser frmListFreeUser = (FrmListFreeUser) FrmListFreeUser.instance();
    dataPackage.nextInt();
    frmListFreeUser.isReceivedData = true;
    int listSize = dataPackage.nextInt();
    Global.freeUser.removeAllElements();
    for (int i = 0; i < listSize; i++) {
      UserBean friend = new UserBean();
      friend.setUsername(dataPackage.nextString());
      friend.setLocationInfo(dataPackage.nextString());
      Global.freeUser.addElement(friend);
    }
  }

  public void onStartGame() {
    GameGlobal.nextState1(Global.currentGame.getGameForm(), null, Transformer.TRANSFORM_WITH_LOADING_FORM);
  }

  public void onGameStartFail(DataPackage dataPackage) {
    int errorCode = dataPackage.nextInt();
    switch (errorCode) {
    case ProtocolConstants.ErrorCode.NOT_ENOUGH_USER_TO_START_GAME_ERROR:
      GameGlobal.alert.showAlert2(this, GameAlert.OK_TYPE, "Không đủ người chơi để bắt đầu", 99);
      break;
    case ProtocolConstants.ErrorCode.USER_NOT_READY_ERROR:
      GameGlobal.alert.showAlert2(this, GameAlert.OK_TYPE, "Có người chơi chưa sẵn sàng", 99);
      break;
    case ProtocolConstants.ErrorCode.NO_AUTHEN_ERROR:
      GameGlobal.alert.showAlert2(this, GameAlert.OK_TYPE, "Mất kết nối với máy chủ", 99);
      break;
    default:
      GameGlobal.alert.showAlert(this, GameAlert.OK_TYPE, "Game bắt đầu thất bại");
      break;
    }
  }

  public void onConfigTableFail(DataPackage dataPackage) {
    int errorCode = dataPackage.nextInt();
    switch (errorCode) {
    case ProtocolConstants.ErrorCode.TABLE_PASSWORD_TOO_LONG_ERROR:
      GameGlobal.alert.showAlert3(this, GameAlert.OK_TYPE, StringArray.create1( "Thiết lập bàn thất bại", "Mật khẩu quá dài" ));
      break;
    case ProtocolConstants.ErrorCode.NOT_ENOUGH_MONEY_TO_SET_TABLE_CONFIG_ERROR:
      GameGlobal.alert.showAlert3(this, GameAlert.OK_TYPE, StringArray.create1( "Thiết lập bàn thất bại", "Bạn không đủ tiền" ));
      break;
    case ProtocolConstants.ErrorCode.NO_AUTHEN_ERROR:
      GameGlobal.alert.showAlert2(this, GameAlert.OK_TYPE, "Mất kết nối với máy chủ", 99);
      break;
    default:
      GameGlobal.alert.showAlert(this, GameAlert.OK_TYPE, "Thiết lập bàn thất bại");
      break;
    }
  }
  
  public void onConfigTableSuccess(DataPackage dataPackage) {
    if (Global.currentGame.getId().equals("audition")) {
      // TODO: disable audition
//      ((FrmTableAutidion) FrmTableAutidion.instance()).isConfigTableDone = true;
    } else {
      ((FrmTable) FrmTable.instance()).isConfigTableDone = true;
    }
  }

  public void onJoinTableSuccess(DataPackage dataPackage) {
    int tableBid = dataPackage.nextInt();
    Global.currentTable.setBid(tableBid);
    
    if (Global.currentGame.getId().equals("audition")) {
      // TODO: disable audition
//      AuditionConstants.playMode = AuditionConstants.ONLINE_MODE;
//      FrmTableAutidion.dontNeedToConfig = false;
//      GameGlobal.nextState1(FrmTableAutidion.instance(), null, Transformer.TRANSFORM_WITH_LOADING_FORM);
    } else {
      FrmTable.dontNeedToConfig = false;
      GameGlobal.nextState1(FrmGroupTableFreeUserFriend.instance(), null, Transformer.TRANSFORM_WITH_LOADING_FORM);
    }
  }
  
  public void onGameUserCountReceive(DataPackage dataPackage) {
    int count = dataPackage.nextInt();
    for (int i = 0; i < count; i++) {
      String gameId = dataPackage.nextString();
      int gameUserCount = dataPackage.nextInt();
      for (int j = 0; j < Constants.GAME_ID.len(); j++) {
        if (Constants.GAME_ID.get(j).equals(gameId)) {
          Constants.GAME_USER_COUNT.set(j, gameUserCount);
          break;
        }
      }
    }
  }

  public void onConfigTableChange(DataPackage dataPackage) {
    int bid = dataPackage.nextInt();
    if (Global.currentGame.getId().equals("audition")) {
      // TODO: disable audition
//      FrmTableAutidion frmTableAutidion = (FrmTableAutidion) FrmTableAutidion.instance();
//      frmTableAutidion.initToCheckReady();
    } else {
      FrmTable frmTable = (FrmTable) FrmTable.instance();
      frmTable.initToCheckReady();
    }

    if (bid != Global.currentTable.getBid()) {
      Global.currentTable.setBid(bid);

      // Nếu người chơi không phải là chủ bàn
      if (!Global.currentUser.getName().equals(Global.currentTable.getTableMasterName())) {
        // Nếu người chơi không đủ tiền
        if (Global.currentUser.getGold() < Global.currentTable.getBid()) {
          GameGlobal.alert.showAlert1(this, GameAlert.OK_TYPE, StringArray.create1("Điểm cược đã thay đổi thành " + bid, "Bạn không đủ tiền để chơi ở bàn này" ), 98);
        } else {
          GameGlobal.alert.showAlert1(this, GameAlert.YES_NO_TYPE, StringArray.create1( "Điểm cược đã thay đổi thành " + bid, "Bạn có muốn chơi tiếp?" ), 97);
        }
      }
    }
  }

  public void onInviteUserToTable(DataPackage dataPackage) {
    // Không hiển thị lời mời trong trường hợp đang chơi game off và đang chuyển form
    GameForm currentForm = Global.systemCanvas.frmCurrent;
    if (currentForm instanceof FrmDaoVangOffline 
        || currentForm instanceof FrmAilaTrieuPhuOff 
        || currentForm instanceof FrmDownloadResource
        || currentForm instanceof FrmAcceptInviteGame) {
      return;
    }
    
    // TODO: disable audition
//    if (currentForm instanceof FrmAuditionOff
//        || currentForm instanceof FrmAuditionOff320x240) {
//      return;
//    }
    
    String fromUserName = dataPackage.nextString();
    invitedGameId = dataPackage.nextString();
    invitedTableId = dataPackage.nextString();
    int bid = 0;
    if (dataPackage.hasMoreData()) {
      bid = dataPackage.nextInt();
    }

    String gameName = "";
    for (int i = 0; i < Constants.GAME_ID.len(); i++) {
      if (Constants.GAME_ID.get(i).equals(invitedGameId)) {
        gameName = Constants.GAME_NAME.get(i);
        break;
      }
    }
    
    if ("".equals(gameName)) {
      return;
    }
    GameGlobal.alert.showAlert1(this, GameAlert.YES_NO_TYPE, StringArray.create2( fromUserName + " mời bạn chơi ", gameName + " đặt cược " + bid + " gold", "Bạn có muốn nhận lời?" ), 96);
  }
  
  public void onInviteUserFail(DataPackage dataPackage) {
    int errorCode = dataPackage.nextInt();
    switch (errorCode) {
    case ProtocolConstants.ErrorCode.USER_BUSY_ERROR:
      Global.alert.showAlert3(this, GameAlert.OK_TYPE, StringArray.create1( "Mời chơi thất bại", "Người chơi đang bận" ));
      break;
    }
  }

  public void onAcceptInviteUserToTable(DataPackage dataPackage) {
    String tableId = dataPackage.nextString();
    String roomId = dataPackage.nextString();
    String gameId = dataPackage.nextString();
    Global.currentGame = (Game) Global.gameMap.get(gameId);
    Global.currentRoom = (Room) roomMap.get(roomId);
    if (Global.currentRoom == null) {
      Global.currentRoom = new Room(roomId);
      roomMap.put(roomId, Global.currentRoom);
    }
    
    Global.currentTable = (Table) tableMap.get(tableId);
    if (Global.currentTable == null) {
      Global.currentTable = new Table(tableId);
      tableMap.put(tableId, Global.currentTable);
    }
    
    if ("audition".equals(gameId)) {
      // TODO: disable audition
//      GameGlobal.nextState1(FrmTableAutidion.instance(), null, Transformer.TRANSFORM_WITH_LOADING_FORM);
    } else {
      GameGlobal.nextState1(FrmGroupTableFreeUserFriend.instance(), null, Transformer.TRANSFORM_WITH_LOADING_FORM);
    }
  }

  public void onAutoFindTable(DataPackage dataPackage) {
    String roomId = dataPackage.nextString();
    String tableId = dataPackage.nextString();
    int tableBid = dataPackage.nextInt();
    Global.currentRoom = (Room) roomMap.get(roomId);
    Global.currentTable = (Table) tableMap.get(tableId);
    Global.currentTable.setBid(tableBid);
    
    if (Global.currentGame.getId().equals("audition")) {
      // TODO: disable audition
//      GameGlobal.nextState(FrmTableAutidion.instance(), null);
    } else {
      GameGlobal.nextState(FrmGroupTableFreeUserFriend.instance(), null);
    }
  }

  public void onJoinTableFail(DataPackage dataPackage) {
    int errorCode = dataPackage.nextInt();
    switch (errorCode) {
    case ProtocolConstants.ErrorCode.TABLE_FULL_ERROR:
      GameGlobal.alert.showAlert2(this, GameAlert.OK_TYPE, "Bàn đã đầy", 92);
      break;
    case ProtocolConstants.ErrorCode.NOT_ENOUGH_MONEY_TO_JOIN_TABLE_ERROR:
      GameGlobal.alert.showAlert2(this, GameAlert.OK_TYPE, "Bạn không đủ tiền để vào bàn", 92);
      break;
    case ProtocolConstants.ErrorCode.TABLE_PASSWORD_WRONG_ERROR:
      GameGlobal.alert.showAlert2(this, GameAlert.OK_TYPE, "Mật khẩu không đúng", 92);
      break;
    case ProtocolConstants.ErrorCode.TABLE_ALREADY_PLAY_ERROR:
      GameGlobal.alert.showAlert2(this, GameAlert.OK_TYPE, "Bàn đang chơi", 92);
      break;
    case ProtocolConstants.ErrorCode.NO_AUTHEN_ERROR:
      GameGlobal.alert.showAlert2(this, GameAlert.OK_TYPE, "Mất kết nối với máy chủ", 99);
      break;
    default:
      GameGlobal.alert.showAlert2(this, GameAlert.OK_TYPE, "Vào bàn thất bại", 92);
      break;
    }
  }

  public void onJoinRoomFail(DataPackage dataPackage) {
    int errorCode = dataPackage.nextInt();
    switch (errorCode) {
    case ProtocolConstants.ErrorCode.NOT_ENOUGN_MONEY_TO_JOIN_ROOM_ERROR:
      GameGlobal.alert.showAlert2(this, GameAlert.OK_TYPE, "Bạn không đủ tiền để vào phòng", 89);
      break;
    case ProtocolConstants.ErrorCode.ROOM_FULL_ERROR:
      GameGlobal.alert.showAlert2(this, GameAlert.OK_TYPE, "Phòng đã đầy", 89);
      break;
    case ProtocolConstants.ErrorCode.NO_AUTHEN_ERROR:
      GameGlobal.alert.showAlert2(this, GameAlert.OK_TYPE, "Mất kết nối với máy chủ", 99);
      break;
    default:
      GameGlobal.alert.showAlert2(this, GameAlert.OK_TYPE, "Vào phòng thất bại", 89);
      break;
    }
  }

  /** Auto invite game */
  public void onAutoNoticeInviteGame(DataPackage dataPackage) {
    if (Global.systemCanvas.frmCurrent instanceof FrmChooseGame) {
      GameGlobal.alert.showAlert1(this, GameAlert.YES_NO_TYPE, GameStringUtils.split(dataPackage.nextString(), "@@@"), 100);
    }
  }

  public void onAutoInviteGameListUser(DataPackage dataPackage) {
    ((FrmAutoInviteGame) FrmAutoInviteGame.instance()).onRecieveData(dataPackage);
  }
  
  public void getTableUserList(DataPackage dataPackage) {
    Global.tableUsers.removeAllElements();
    Vector users = new Vector();
    int index = -1;
    String tableMasterName = dataPackage.nextString();
    Global.currentTable.setTableMasterName(tableMasterName);

    int size = dataPackage.nextInt();
    for (int i = 0; i < size; i++) {
      String username = dataPackage.nextString();
      boolean isReady = dataPackage.nextInt() == 0 ? false : true;
      String avatarId = dataPackage.nextString();
      int isViewUser = dataPackage.nextInt();

      User user = (User) Global.userCachedMap.get(username);
      if (user == null) {
        user = new User(username);
      }
      user.setReady(isReady);
      user.setAvatarId(avatarId);
      user.setViewUser(isViewUser == 1);

      users.addElement(user);
      Global.userCachedMap.put(user.getName(), user);
      if (user.equals(Global.currentUser)) {
        index = i;
        Global.currentUser.setReady(user.isReady());
        Global.currentUser.setAvatarId(user.getAvatarId());
        Global.currentUser.setViewUser(user.isViewUser());
      } else {
        SocketClientUtil.requestUserInfo(username);
      }
    }

    // Đưa người dùng hiện tại lên đầu danh sách
    if (index == -1 || index == 0) {
      for (int i = 0; i < users.size(); i++) {
        Global.tableUsers.addElement(users.elementAt(i));
      }
    } else {
      for (int i = index; i < users.size(); i++) {
        Global.tableUsers.addElement(users.elementAt(i));
      }
      for (int i = 0; i < index; i++) {
        Global.tableUsers.addElement(users.elementAt(i));
      }
    }

    if (Global.chatComponent != null) {
      Global.chatComponent.updateChatList(Global.tableUsers);
    }
  }

  public void getTableList(DataPackage dataPackage) {
    String roomId = dataPackage.nextString();
    Room room = (Room) roomMap.get(roomId);
    if (room == null) {
      return;
    }

    room.clearChildList();
    tableMap.removeAll();
    int size = dataPackage.nextInt();
    for (int i = 0; i < size; i++) {
      Table table = new Table(dataPackage.nextString());
      table.setName(dataPackage.nextString());
      table.setBid(dataPackage.nextInt());
      table.setLocked(dataPackage.nextInt() == 0 ? false : true);
      table.setConcurrentUser(dataPackage.nextInt());
      table.setMaxUser(dataPackage.nextInt());
      table.setPlaying(dataPackage.nextInt() == 0 ? false : true);
      room.putChild(table);
      tableMap.put(table.getId(), table);
    }
    FrmListTable frmListTable = (FrmListTable) FrmListTable.instance();
    frmListTable.updateTableList();
  }

  public void getRoomList(DataPackage dataPackage) {
    String gameId = dataPackage.nextString();
    Game game = (Game) Global.gameMap.get(gameId);
    if (game == null) {
      return;
    }

    if (Global.currentGame == null) {
      Global.currentGame = game;
    }

    game.clearChildList();
    roomMap.removeAll();
    int size = dataPackage.nextInt();
    for (int i = 0; i < size; i++) {
      Room room = new Room(dataPackage.nextString());
      room.setName(dataPackage.nextString());
      room.setType(dataPackage.nextInt());
      room.setConcurrentUser(dataPackage.nextInt());
      room.setMaxUser(dataPackage.nextInt());
      room.setMaxUserPerTable(dataPackage.nextInt());
      room.setMinBid(dataPackage.nextInt());
      room.setMaxBid(dataPackage.nextInt());
      game.putChild(room);
      roomMap.put(room.getId(), room);
    }
    FrmListRoom frmListRoom = (FrmListRoom) FrmListRoom.instance();
    frmListRoom.updateRoomList();
  }
  
  public void onKickUserSuccess(DataPackage dataPackage) {
    String userWasKicked = dataPackage.nextString();
    Global.alert.showAlert3(this, GameAlert.OK_TYPE, StringArray.create1("Đã kick user " + userWasKicked, "thành công"));
  }
  
  public void onKickUserFail(DataPackage dataPackage) {
    String userCanNotKick = dataPackage.nextString();
    Global.alert.showAlert3(this, GameAlert.OK_TYPE, StringArray.create1("Kick user " + userCanNotKick, "thất bại"));
  }
  
  public void onKickedOutOfTable(DataPackage dataPackage) {
    if (!(Global.systemCanvas.frmCurrent instanceof FrmDownloadResource)) {
      Global.nextState(FrmGroupListTableFreeUserChat.instance(), null);
    }
    
    new GameControl() {
      public void perform() {
        Global.alert.showAlert3(GameBussiness.this, GameAlert.OK_TYPE, StringArray.create1("Bạn đã bị kick", "ra khỏi bàn"));
      }
    }.setTimeInterval(1000).start();
  }
  
  public void onNotEnoughMoneyToPlayGameOff(DataPackage dataPackage) {
    int fee = dataPackage.nextInt();
    GameGlobal.alert.showCustomButtonAlert1(this, StringArray.create2("Đổi gold", "Nạp tiền", "Trở về"), GameAlert.BUTTON_WIDTH_LARGE, StringArray.create1("Bạn không đủ " + fee + " gold để chơi", "Hãy nạp thêm gold!"), 90, GameAlert.VERTICAL_ALINE);
  }
}
